package com.fjnu.dao.impl;

import com.fjnu.dao.UserDao;
import com.fjnu.domain.dto.UserConditionDto;
import com.fjnu.domain.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Repository
public class UserDaoImpl implements UserDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public int insert(User newUser) {
        if (newUser == null || newUser.getName() == null || newUser.getName().trim().isEmpty() ||
                newUser.getPassword() == null || newUser.getPassword().trim().isEmpty()) {
            return 0;
        }

        String sql = "INSERT INTO tb_user(name, password, salt, create_time, gender, score, status, email) " +
                "VALUES(?, ?, ?, NOW(), ?, ?, ?, ?)";
        return jdbcTemplate.update(sql,
                newUser.getName(),
                newUser.getPassword(),
                newUser.getSalt(),
                newUser.getGender(),
                newUser.getScore(),
                newUser.getStatus(),
                newUser.getEmail()
        );
    }

    @Override
    public int insertUserRole(Integer userId, Integer roleId) {
        if (userId == null || roleId == null) {
            return 0;
        }
        String sql = "INSERT INTO tb_user_role(user_id, role_id) VALUES(?, ?)";
        return jdbcTemplate.update(sql, userId, roleId);
    }

    @Override
    public int batchInsertUserRoles(Integer userId, List<Integer> roleIds) {
        if (userId == null || roleIds == null || roleIds.isEmpty()) {
            return 0;
        }

        String sql = "INSERT INTO tb_user_role(user_id, role_id) VALUES(?, ?)";
        List<Object[]> batchArgs = new ArrayList<>();
        for (Integer roleId : roleIds) {
            batchArgs.add(new Object[]{userId, roleId});
        }
        int[] results = jdbcTemplate.batchUpdate(sql, batchArgs);
        return (int) Arrays.stream(results).filter(result -> result > 0).count();
    }

    @Override
    public int updatePassword(Integer userId, String newPassword) {
        if (userId == null || newPassword == null || newPassword.trim().isEmpty()) {
            return 0;
        }
        String sql = "UPDATE tb_user SET password = ? WHERE user_id = ?";
        return jdbcTemplate.update(sql, newPassword, userId);
    }

    @Override
    public int updateScore(Integer userId, Long incrementedScore) {
        if (userId == null || incrementedScore == null) {
            return 0;
        }
        String sql = "UPDATE tb_user SET score = score + ? WHERE user_id = ?";
        return jdbcTemplate.update(sql, incrementedScore, userId);
    }

    @Override
    public User selectByNameAndPwd(String username, String password) {
        if (username == null || username.trim().isEmpty() || password == null || password.trim().isEmpty()) {
            return null;
        }

        String sql = "SELECT * FROM tb_user WHERE name = ? AND password = ?";
        List<User> users = jdbcTemplate.query(sql,
                new BeanPropertyRowMapper<>(User.class), username, password);
        return users.isEmpty() ? null : users.get(0);
    }

    @Override
    public List<User> selectByCondition(UserConditionDto userCondition) {
        if (userCondition == null) {
            return new ArrayList<>();
        }

        StringBuilder sql = new StringBuilder("SELECT * FROM tb_user WHERE 1=1");
        List<Object> params = new ArrayList<>();

        if (userCondition.getUsername() != null && !userCondition.getUsername().isEmpty()) {
            sql.append(" AND name LIKE ?");
            params.add("%" + userCondition.getUsername() + "%");
        }
        if (userCondition.getEmail() != null && !userCondition.getEmail().isEmpty()) {
            sql.append(" AND email LIKE ?");
            params.add("%" + userCondition.getEmail() + "%");
        }
        if (userCondition.getStatus() != null) {
            sql.append(" AND status = ?");
            params.add(userCondition.getStatus());
        }
        if (userCondition.getMinScore() != null) {
            sql.append(" AND score >= ?");
            params.add(userCondition.getMinScore());
        }
        if (userCondition.getMaxScore() != null) {
            sql.append(" AND score <= ?");
            params.add(userCondition.getMaxScore());
        }

        return jdbcTemplate.query(sql.toString(),
                new BeanPropertyRowMapper<>(User.class), params.toArray());
    }

    @Override
    public List<User> selectByConditionWithLimit(UserConditionDto userCondition, Integer startIndex, Integer endIndex) {
        if (userCondition == null || startIndex == null || endIndex == null || startIndex < 0 || endIndex <= startIndex) {
            return new ArrayList<>();
        }

        StringBuilder sql = new StringBuilder("SELECT * FROM tb_user WHERE 1=1");
        List<Object> params = new ArrayList<>();

        if (userCondition.getUsername() != null && !userCondition.getUsername().isEmpty()) {
            sql.append(" AND name LIKE ?");
            params.add("%" + userCondition.getUsername() + "%");
        }
        if (userCondition.getEmail() != null && !userCondition.getEmail().isEmpty()) {
            sql.append(" AND email LIKE ?");
            params.add("%" + userCondition.getEmail() + "%");
        }
        if (userCondition.getStatus() != null) {
            sql.append(" AND status = ?");
            params.add(userCondition.getStatus());
        }
        if (userCondition.getMinScore() != null) {
            sql.append(" AND score >= ?");
            params.add(userCondition.getMinScore());
        }
        if (userCondition.getMaxScore() != null) {
            sql.append(" AND score <= ?");
            params.add(userCondition.getMaxScore());
        }

        sql.append(" LIMIT ?, ?");
        params.add(startIndex);
        params.add(endIndex - startIndex);

        return jdbcTemplate.query(sql.toString(),
                new BeanPropertyRowMapper<>(User.class), params.toArray());
    }
}